// 3242. 设计相邻元素求和服务
// class NeighborSum
// {
// public:
//     NeighborSum(vector<vector<int>> &grid)
//     {
//         int n = grid.size();
//         for (int i = 0; i < grid.size(); i++)
//         {

//             for (int j = 0; j < grid.size(); j++)
//             {
//                 vector<int> data(2, 0);
//                 for (int k = 0; k < 8; k++)
//                 {
//                     int x = i + dirs[k][0];
//                     int y = j + dirs[k][1];
//                     if (x >= 0 && x < n && y >= 0 && y < n)
//                     {
//                         data[k / 4] += grid[x][y];
//                     }
//                 }
//                 um[grid[i][j]] = data;
//             }
//         }
//     }

//     int adjacentSum(int value)
//     {
//         return um[value][0];
//     }

//     int diagonalSum(int value)
//     {
//         return um[value][1];
//     }

// private:
//     static constexpr int dirs[8][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {1, 1}, {-1, 1}, {-1, -1}, {1, -1}};
//     unordered_map<int, vector<int>> um;
// };

/**
 * Your NeighborSum object will be instantiated and called as such:
 * NeighborSum* obj = new NeighborSum(grid);
 * int param_1 = obj->adjacentSum(value);
 * int param_2 = obj->diagonalSum(value);
 */
#include <unistd.h>
#include "APILock.hpp"
#include <pthread.h>
#include <iostream>
#include <string>
pthread_mutex_t mutex;
pthread_cond_t cond;
int count = 0;
void *print1(void *arge)
{
    // pthread_mutex_lock(&mutex);
    std::string s = static_cast<const char *>(arge);

    while (true)
    {
        APIlock lock(&mutex);
        // pthread_mutex_lock(&mutex);
        while (count % 2 == 1)
        {
            pthread_cond_signal(&cond);
            pthread_cond_wait(&cond, &mutex);
        }
        std::cout << s << ' ' << count << std::endl;
        count++;
        // pthread_mutex_unlock(&mutex);
        sleep(1);
    }
    // pthread_mutex_unlock(&mutex);
}
void *print2(void *arge)
{
    // pthread_mutex_lock(&mutex);
    std::string s = static_cast<const char *>(arge);
    while (true)
    {
        APIlock lock(&mutex);
        // pthread_mutex_lock(&mutex);
        while (count % 2 == 0)
        {
            pthread_cond_signal(&cond);
            pthread_cond_wait(&cond, &mutex);
            
        }
        std::cout << s << ' ' << count << std::endl;
        count++;
        sleep(1);
        // pthread_mutex_unlock(&mutex);
    }
}
int main()
{
    pthread_mutex_init(&mutex, nullptr);
    pthread_cond_init(&cond, nullptr);
    pthread_t A, B;
    pthread_create(&A, nullptr, print1, (void *)"我是线程A");
    pthread_create(&B, nullptr, print2, (void *)"我是线程B");
    pthread_join(A, nullptr);
    pthread_join(B, nullptr);
}
using namespace std;
#include <vector>
#include <cmath>
#include <functional>
#include <thread>
// class Foo
// {
// public:
//     Foo()
//     {
//         int tem[3];
//         for (int i = 0; i < 3; i++)
//         {
//             cin >> tem[i];
//         }
//         vector<function<void(function<void()>)> *> fun[3] = {first, second, third};
//         function<void()> fun1=first;
//         // fun.push_back(first);
//         for (int i = 3; i >= 0; i--)
//         {
//             thread(fun[tem[i] / (int)pow(10, i)]);
//         }
//     }

//     void first()
//     {

//         // printFirst() outputs "first". Do not change or remove this line.
//         //printFirst();
//     }

//     void second(function<void()> printSecond)
//     {

//         // printSecond() outputs "second". Do not change or remove this line.
//         printSecond();
//     }

//     void third(function<void()> printThird)
//     {

//         // printThird() outputs "third". Do not change or remove this line.
//         printThird();
//     }
// };
//1114. 按序打印
//条件变量+互斥
class Foo {
    int flag=0;
    pthread_mutex_t mutex1;
    pthread_cond_t cond;
public:
    Foo() {
        pthread_mutex_init(&mutex1, nullptr);
        pthread_cond_init(&cond, nullptr);
    }

    void first(function<void()> printFirst) {
        pthread_mutex_lock(&mutex1);
        // printFirst() outputs "first". Do not change or remove this line.
        printFirst();
        
        flag=1;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex1);
    }

    void second(function<void()> printSecond) {
        pthread_mutex_lock(&mutex1);
        while(flag!=1)
        {    
            pthread_cond_signal(&cond);
            pthread_cond_wait(&cond,&mutex1);
        }
        // printSecond() outputs "second". Do not change or remove this line.
        printSecond();
        flag=2;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex1);
    }

    void third(function<void()> printThird) {
        pthread_mutex_lock(&mutex1);
        while(flag!=2)
        {    
            pthread_cond_signal(&cond);
            pthread_cond_wait(&cond,&mutex1);
        }
        // printThird() outputs "third". Do not change or remove this line.
        printThird();
        pthread_mutex_unlock(&mutex1);
    }
};

//信号量实现
class Foo {
    sem_t s1,s2;
public:
    Foo() {
        sem_init(&s1,0,0);
        sem_init(&s2,0,0);
    }

    void first(function<void()> printFirst) {
        
        // printFirst() outputs "first". Do not change or remove this line.
        printFirst();
        sem_post(&s1);//s1++;
    }

    void second(function<void()> printSecond) {
        sem_wait(&s1);//s1--;
        // printSecond() outputs "second". Do not change or remove this line.
        printSecond();
        sem_post(&s2);//s2++
    }

    void third(function<void()> printThird) {
        sem_wait(&s2);//s2--
        // printThird() outputs "third". Do not change or remove this line.
        printThird();
    }
};